#include "synccontroller.h"

#include "QtNetwork/QNetworkInterface"

#include "dao/aqfornecedordao.h"



#define CONNECT_SERVICE_SIGNALS(serviceName) \
QObject::connect(&service##serviceName,SIGNAL(responseReceived(const QByteArray&)), \
                 this,SLOT(serviceName##Received(const QByteArray &))); \
QObject::connect(&service##serviceName,SIGNAL(networkError(QNetworkReply::NetworkError)), \
                 this,SLOT(serviceName##Error(QNetworkReply::NetworkError)));

#define IMPORT_CSV(nomeEntidade, response) \
{ \
    nomeEntidade##DAO dao; \
    if(!importCSV(&dao,QString(response),#nomeEntidade)) return; \
}

#define POST_CSV(nomeEntidade,where) \
{ \
    nomeEntidade##DAO daoEntidade; \
    if(!postCSV(&daoEntidade,service##nomeEntidade,#nomeEntidade,where)) return; \
}

SyncController::SyncController(QObject *parent) :
    QObject(parent)
{
    QString mac = getMacAddress();

    serviceAQFornecedor.setUrl(MAIN_URL "/AQFornecedor?UID="+mac);
    CONNECT_SERVICE_SIGNALS(AQFornecedor);

    serviceUpdatePos.setUrl(MAIN_URL "/UpdatePos?UID="+mac);
    CONNECT_SERVICE_SIGNALS(UpdatePos);
}

QString SyncController::getMacAddress()
{
    QString result;
    foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
    {
        if(interface.flags() & QNetworkInterface::IsLoopBack) continue;
        if(interface.hardwareAddress().length()>1) {
            result = interface.hardwareAddress();
            break;
        }
    }
    return result;
}

template<class T>
bool SyncController::importCSV(T *dao, QString response, QString nomeEntidade)
{
    try {
        if(response.startsWith("{\"error\":")) {
            emit loadError();
            return false;
        }
        dao->importCSV(QString(response));
    } catch(DatabaseException& e) { \
        qDebug(QString("Erro importando os dados de ").append(nomeEntidade).toUtf8());
        emit loadError();
        return false;
    }

    return true;
}

template<class T>
bool SyncController::postCSV(T *daoEntidade, GenericService &genericService, QString nomeEntidade, QString where)
{
    try {
        QString content = daoEntidade->createCSV(where);
        content = Utils::StringMD5(content) + "\n" + content;
        genericService.post(&service,content);
    } catch(DatabaseException& e) {
        qDebug(QString("Erro exportandos os dados de ").append(nomeEntidade).toUtf8());
        emit sendError();
        return false;
    }

    return true;
}


void SyncController::UpdatePosReceived(const QByteArray &response) {
    qDebug("update complete!");

    try {
        AQFornecedorDAO dao;
        dao.save(fornecedorSincronizando);
    } catch(DatabaseException& e) { }

    delete fornecedorSincronizando;
    emit sendComplete();
}

void SyncController::UpdatePosError(QNetworkReply::NetworkError err) {
    qDebug("update error!");

    delete fornecedorSincronizando;
    emit sendError();
}


void SyncController::startSync() {
    serviceAQFornecedor.get(&service);
}

//

void SyncController::AQFornecedorReceived(const QByteArray &response) {
    IMPORT_CSV(AQFornecedor,response);
    emit loadComplete();
}

void SyncController::AQFornecedorError(QNetworkReply::NetworkError err) {
    emit loadError();
}

QVariantList SyncController::loadFornecedores() {
    QVariantList result;

    AQFornecedorDAO dao;
    GenericListModel *list = dao.findAll();

    QList<QObject *> entries = list->getEntries();
    for(int i=0; i<entries.length(); i++) {
        AQFornecedor *fornecedor = (AQFornecedor *)entries[i];
        QVariantMap dadosFornecedor;

        dadosFornecedor.insert("id",QString::number(fornecedor->mId()));
        dadosFornecedor.insert("nome",fornecedor->Nome());
        dadosFornecedor.insert("lat",fornecedor->PosLatitude());
        dadosFornecedor.insert("lon",fornecedor->PosLongitude());

        result.append(dadosFornecedor);
    }

    return result;
}

void SyncController::updatePos(QString id, QString lat, QString lon) {
    AQFornecedorDAO dao;
    fornecedorSincronizando = dao.findById(id.toLong());

    if(fornecedorSincronizando) {
        fornecedorSincronizando->setPosLatitude(lat);
        fornecedorSincronizando->setPosLongitude(lon);

        QString args = QString("&id=").append(id).append("&lat=").append(lat).append("&lon=").append(lon);
        serviceUpdatePos.get(&service,args);
    } else {
        emit sendError();
    }
}
